<?php
/**
 * Clase que gestiona las canciones
 */
class Cancion{
	/**
	 * Clase para la conexión a la BBDD
	 * @var Object
	 */
	private $MySQL;
	
	/**
	 * Identificador
	 * @var integer
	 */
	private $id;
	
	/**
	 * Identificador del usuario
	 * @var integer
	 */
	private $id_usuario;
	
	/**
	 * Titulo
	 * @var string
	 */
	private $titulo;
	
	/**
	 * Artista
	 * @var string
	 */
	private $artista;
	
	/**
	 * Album
	 * @var srting
	 */
	private $album;
	
	/**
	 * Fecha de subida
	 * @var integer
	 */
	private $fecha;
	
	/**
	 * Géneros de la canción
	 * @var array indexado por id y nombre
	 */
	private $lista_generos=array();
	
	/**
	 * Tipo del archivo
	 * @var string $tipo
	 */
	private $tipo;

	/**
	 * Longitud del archivo
	 * @var integer $longitud
	 */
	private $longitud;
	
	private $descripcion;
	
	private $extension;

        /**
         * Array de los comentarios de la canción,
         * @var <array>  indexado por id, usuario, cancion, comentario, borrado
         */
	private $comentarios;
	/*
	 * Métodos de la Clase.
	 ***********************/	

	/**
	 * Constructor
	 * 
	 * Si recibe un identificador válido, se carga la canción de la BBDD mediante el método {@link cargar()}, en caso contrario crea un objeto
	 * vacío.
	 * @see cargar()
	 * 
	 * @param integer $id
	 */
	public function __construct($id_cancion=null){
            $Validar = new Validar();
            $this->MySQL = new MySQL('MYLIED');

            if($Validar->id($id_cancion)){
                $this->id = $id_cancion;
                $this->cargar();
            }
	}

	/**
	 * Carga todos los datos para el cancion en la BBDD.
	 * 
	 * Este método es invocado cuando se le pasa un id de Cancion válido al constructor, y a partir
	 * de éste se cargan todos sus datos de la BBDD.
	 */
	private function cargar(){
            try{
                if($this->id){
                    $query_cancion = "SELECT *
                                        FROM canciones
                                        WHERE id = '$this->id'; ";
                    if(!($result = $this->MySQL->query($query_cancion)))
                        throw new Exception("Error al cargar la canci&oacute;n");
                    else if(mysql_num_rows($result) == 0)
                        throw new Exception("La informaci&oacute;n de la canci&oacute;n no est&aacute; disponible.");

                    $row = mysql_fetch_array($result);

                    $this->id_usuario = $row['fk_usuario'];
                    $this->titulo = $row['titulo'];
                    $this->artista = $row['artista'];
                    $this->album = $row['album'];
                    $this->fecha = $row['fecha'];
                    $this->descripcion = $row['descripcion'];
                    $this->longitud = $row['longitud'];
                    $this->tipo = $row['tipo'];
                    $this->extension = $row['extension'];

                    $this->cargar_Generos();
                    $this->cargar_Comentarios();
                }
            }catch(Exception $e){}
	}	
	
	private function cargar_Generos(){
            $query = "SELECT generos_canciones.*
                        FROM generos_canciones
                            INNER JOIN canciones_rel_generos ON canciones_rel_generos.fk_genero = generos_canciones.id
                                                                            AND canciones_rel_generos.fk_cancion='$this->id';";

            if(!($result = $this->MySQL->query($query)))
                throw new Exception("Error al cargar la lista de g&eacute;neros de la canci&oacute;n");

            while($row=mysql_fetch_array($result)){
                $this->lista_generos[] = $row;
            }
	}
	
	private function cargar_Comentarios(){
		
            $this->comentarios=array();

            $query = "SELECT comentarios.id, comentarios.fk_usuario as usuario, comentarios.fk_cancion as cancion, comentarios.comentario, comentarios.borrado
                        FROM comentarios
                            WHERE comentarios.fk_cancion='$this->id' AND NOT comentarios.borrado ORDER BY id DESC;";
            //FB::info($query);
            if(!($result = $this->MySQL->query($query)))
                throw new Exception("Error al cargar la lista de comentarios de la canci&oacute;n");

            while($row=mysql_fetch_array($result)){
                $this->comentarios[$row['id']] = $row;
            }
	}
	/**
	 * Devuelve el id del disco
	 * 
	 * @return integer $id Id de la canci&oacute;n.
	 */
	public function get_Id(){
            return $this->id;
	}
	
	/**
	 * Devuelve el id del usuario
	 * 
	 * @return integer
	 */
	public function get_Id_Usuario(){
            return $this->id_usuario;
	}
	
	/**
	 * Devuelve el titulo del canción
	 * 
	 * @return string $titulo
	 */
	public function get_Titulo(){
            return $this->titulo;
	}
	/**
	 * Devuelve el tipo de canción
	 * 
	 * @return string $artista
	 */
	public function get_Artista(){
            return $this->artista;
	}
	
	/**
	 * Devuelve el albumo del canción
	 * 
	 * @return string $album
	 */
	public function get_Album(){
            return $this->album;
	}
	
	/**
	 * Indica si el canción es duro o removible
	 * 
	 * @return string $fecha
	 */
	public function get_Fecha(){
            return $this->fecha;
	}

	public function get_Descripcion(){
            return $this->descripcion;
	}
	public function get_Longitud(){
            return $this->longitud;
	}
	public function get_Tipo(){
            return $this->tipo;
	}	
	public function get_Extension(){
            return $this->extension;
	}

        /**
         * Devuelve el array con los comentarios de la canción
         * @return <array>  indexado por id, usuario, cancion, comentario, borrado
         */
	public function get_Comentarios(){
            return $this->comentarios;
	}
	/**
	 * Borra la canción de la BBDD
	 */
	public function del_Cancion(){
            $query = "DELETE FROM canciones WHERE id='$this->id'";
            $this->MySQL->query($query);

            $this->unset_Archivo();

            $query = "DELETE FROM listas_favoritas WHERE fk_cancion='$this->id'";
            $this->MySQL->query($query);

            $query = "DELETE FROM comentarios WHERE fk_cancion='$this->id'";
            $this->MySQL->query($query);
	}
	
	/**
	 * Devuelve la lista de géneros
	 * 
	 * @return array $lista Array indexado por id y titulo
	 */
	public function get_Generos(){
            return $this->lista_generos;
	}
	
	public function get_Generos_Print(){
            if($this->lista_generos){
                $generos=array();
                foreach($this->lista_generos as $genero)
                    $generos[] = $genero['nombre'];
                    $generos = implode(" ",$generos);

                return $generos;
            }
            return null;
	}
	
	public function get_Nombre_Archivo(){
            return $this->id.".".$this->extension;
	}

        public function get_Nombre(){
            return $this->get_Titulo()." - ".$this->get_Artista();
        }

        public function get_Nombre_Cancion(){
            return $this->get_Titulo()." - ".$this->get_Artista().".".$this->get_Extension();
        }
	
	public function crear($datos){
		
            $ListaCanciones = new ListaCanciones();

            $array_generos = $ListaCanciones->lista_Generos();

            //Comprobando los datos "imprescindibles":
            $errores = '';
            if($datos['titulo'] == '' || ! isset($datos['titulo']))
                $errores .= "<p>El t&iacute;tulo es obligatorio.</p>";

            if($datos['artista'] == '' || ! isset($datos['artista']))
                $errores .= "<p>El artista/grupo es obligatorio.</p>";

            $genero_error = false;
            if(isset($datos['generos']))
            foreach($datos['generos'] as $id_genero){
                if(!is_numeric($id_genero) || !in_array($id_genero, array_keys($array_generos))){
                    $errores .= "<p>Se han especificado g&eacute;neros inv&aacute;lidos.</p>";
                    break;
                }
            }

            if(!isset($datos['fichero']['name']) || !isset($datos['fichero']['tmp_name']) ||
                !isset($datos['fichero']['type']) || !isset($datos['fichero']['size']))
                $errores .= "<p>Datos de archivo inv&aacute;lidos</p>";

            else{
                $extension = Cancion::extension_archivo($datos['fichero']['name']);
                if($extension != 'mp3')
                    $errores .= "<p>De momento s&oacute;lo se admiten mp3</p>";
            }

            if($errores != '') {
                throw new Exception($errores);
            }

            $Login = unserialize($_SESSION['login']);
            $this->id_usuario = $Login->get_User();

            $usuario = new Usuario($this->id_usuario);

            //Número límite de canciones subidas?
            if(!$usuario->es_Admin())
            if(!($usuario->get_Num_Canciones_Hoy() < 2))
                throw new Exception('Ya has alcanzado el l&iacute;mite de canciones diario.');

            //Si todo ha ido bien:
            $this->titulo = stripslashes(trim($datos['titulo']));
            $this->extension = $extension;
            $this->artista = stripslashes(trim(mysql_real_escape_string($datos['artista'])));
            $this->fecha = time();
            $this->album = stripslashes(trim(mysql_real_escape_string($datos['album'])));
            $this->descripcion = stripslashes(trim(mysql_real_escape_string($datos['descripcion'])));

            $this->tipo = $datos['fichero']['type'];
            $this->longitud = $datos['fichero']['size'];


            $this->guardar();
            $this->guardar_Archivo($datos['fichero']);
            if(isset($datos['generos']))
            $this->add_Generos($datos['generos']);

            return $this->id;
	}
	
	function extension_archivo ($ruta) {
	    $res = explode(".", $ruta);
	    $extension = $res[count($res)-1];
	    return $extension ;
	}
	/**
	 * Guarda en la BBDD los datos de la canción
	 */
	private function guardar(){
            $campos = "";
            $valores = "";

            if($this->artista){
                $campos .= ",artista";
                $valores .= ",'".mysql_real_escape_string($this->artista)."'";
            }
            if($this->album){
                $campos .= ",album";
                $valores .= ",'".mysql_real_escape_string($this->album)."'";
            }
            if($this->descripcion){
                $campos .= ",descripcion";
                $valores .= ",'".mysql_real_escape_string($this->descripcion)."'";
            }

            $query = "INSERT INTO canciones (titulo, fecha, fk_usuario,tipo,longitud,extension $campos)
                                        VALUES (
                                                '".mysql_real_escape_string($this->titulo)."',
                                                '$this->fecha',
                                                '$this->id_usuario',
                                                '$this->tipo',
                                                '$this->longitud',
                                                '$this->extension'
                                                $valores
                                                );";
            if(!$this->MySQL->query($query))
                throw new Exception("Error al crear la canci&oacute;n".$query);

            $this->id = mysql_insert_id();
	}

        /**
         * Añade los generados dados por su id a la canción
         * @param <array> $ids_generos
         */
	public function add_Generos($ids_generos){
            try{
                foreach($ids_generos as $id_genero){
                    $this->add_Genero($id_genero);
                }
            }catch(Exception $e){
                $this->del_Cancion();
                throw new Exception($e->getMessage());
            }
	}

        /**
         * Agrega el género dado por su id a la canción
         * @param <integer> $id_genero
         */
	public function add_Genero($id_genero){
		
            if(!in_array($id_genero, array_keys($this->lista_generos))){
                $query = "INSERT INTO canciones_rel_generos (fk_cancion, fk_genero) VALUES ('$this->id', '$id_genero');";
                if(!$this->MySQL->query($query))
                    throw new Exception("Error al a&ntilde;adir el g&eacute;nero.");

                $q="SELECT * FROM generos_canciones WHERE id='$id_genero'";
                $rs=$this->MySQL->query($q);
                $row = mysql_fetch_array($rs);

                $this->lista_generos[$row['id']] = $row['nombre'];
            }
	}

        /**
         * Crea un comentario y lo agrega a la canción
         * @param <string> $comentario
         * @param <integer> $id_usuario usuario que publica el comentario
         * @return <integer> $id_comentario
         */
	public function add_Comentario($comentario,$id_usuario){
		
            if($comentario && $comentario!='' && $id_usuario){

                $datos['id_usuario'] = $id_usuario;
                $datos['id_cancion'] = $this->id;
                $datos['comentario'] = $comentario;
                $comment = new Comentario();
                $id_comentario = $comment->crear($datos);

            }else
                throw new Exception("El comentario no puede estar vac&iacute;o");

            $this->cargar_Comentarios();

            return $id_comentario;
	}

        /**
         * Marca el comentario dado por su id como borrado, pero no lo borra de la bbdd
         * @param <integer> $id_comentario
         */
	public function del_Comentario($id_comentario){
            if(in_array($id_comentario, array_keys($this->comentarios))){
                $query = "UPDATE comentarios set borrado=1 WHERE id='$id_comentario'";
                if(!$rs=$this->MySQL->query($query))
                    throw new Exception("Error al borrar el comentario");

                $this->cargar_Comentarios();
            }
	}	
		
	
	/* ******************************************************
	 *             OPERACIONES SOBRE LOS ARCHIVOS
	 * ******************************************************
	 */
	
	
	/**
	 * Función que realiza la subida del archivo. En caso de haber algún problema borra la canción recién creada
	 * @param array $datos_fichero Array indexado por 'name', 'tmp_name', 'type' y 'size'
	 */
	private function guardar_Archivo($datos_fichero){
            if(is_uploaded_file($datos_fichero['tmp_name']) && file_exists($datos_fichero['tmp_name'])){

                //Definiendo el formato del titulo en el sistema de ficheros:
                $nombre_archivo = $this->id.".".$this->extension;

                if(!file_exists(UPLOAD_PATH.$nombre_archivo))
                    move_uploaded_file($datos_fichero['tmp_name'], UPLOAD_PATH.$nombre_archivo);
                else
                    throw new Exception("Est&aacute;s subiendo dos veces el mismo archivo.");

            }else{
                $this->del_Cancion();
                throw new Exception("Error en la subida del archivo .");
            }

            return $nombre_archivo;
	}
	
	/**
	 * Elimina el archivo del directorio
	 */
	public function unset_Archivo(){
            if(file_exists(UPLOAD_PATH.$this->id.".".$this->extension) && is_writable(UPLOAD_PATH.$this->id.".".$this->extension))
                unlink(UPLOAD_PATH.$this->id.".".$this->extension);
	}
	
	/**
	 * Devuelve el archivo
	 */
	public function get_Archivo(){
            if(!file_exists(UPLOAD_PATH.$this->id.".".$this->extension))
                throw new Exception("Archivo no encontrado");
            else if(!is_readable(UPLOAD_PATH.$this->id.".".$this->extension))
                throw new Exception("Error: El archivo no se puede leer" );

            return file_get_contents(UPLOAD_PATH.$this->id.".".$this->extension);
	}
	
	/**
	 * Devuelve el tamaño del archivo en formato "legible".
	 * 
	 * @return string $size Tamaño del archivo debidamente formateado.
	 */
	public function get_Hum_Size(){
		$size = $this->longitud;
		$i=0;
		$iec = array("B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB");
		while (($size/1024)>1){
			$size=$size/1024;
			$i++;
		}
		
		return substr($size,0,strpos($size,'.')+2).$iec[$i];
	}
}
?>